# ~*~ coding: utf-8 ~*~
from flask import request, views, render_template, jsonify
from flask_login import current_user

from apps.common.utils import fill_date_to_timestamp, timestamp_obj_to_str, list2dict
from apps.common.mixin import CompatibleWithSelect2Mixin
from apps.extensions import db
from apps.common import response
from apps.perms.mixin import LoginRequiredMixin
from ..models import Filter, Project
from ..forms import FilterForm
from ..mixin import FilterPermissionMixin


__all__ = [
    'FilterListAPI', 'FilterListView',
    'FilterCreateView', 'FilterUpdateView',
    'FilterDeleteView'
]


class FilterListAPI(CompatibleWithSelect2Mixin, FilterPermissionMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'codes-filter-list'

    def get_queryset(self):
        project_ids = self.get_filter()
        if request.args.get('project'):
            project_id = request.args.get('project')
            if project_id in project_ids:
                # 用户筛选的过滤条件
                return db.session.query(Filter).filter(Filter.project_id == project_id)

        # 默认权限的过滤条件
        return db.session.query(Filter).filter(Filter.project_id.in_(project_ids))

    def get(self):
        create_time = request.args.get('create_time')
        start_time = end_time = None
        if create_time:
            start_time = fill_date_to_timestamp('start', create_time.split('~')[0])
            end_time = fill_date_to_timestamp('end', create_time.split('~')[1])

        filter_conditions = {
            'and': [
                ('create_time', 'gte', start_time),
                ('create_time', 'lte', end_time),
            ],
            'or': [
                ('filename', 'like', request.args.get('search')),
            ],
        }

        # 排序
        sort = request.args.get('sort') or 'create_time'
        order = request.args.get('order') or 'desc'
        order_by_list = [(sort, order), ]

        # 分页
        offset = request.args.get('offset') or 0
        limit = request.args.get('limit') or 12

        # Compatible with select2
        if request.values.get('type') == 'select2':
            filter_conditions, order_by_list, offset, limit = self.select2_queryset()

        filters, count = Filter.get_queryset(queryset=self.get_queryset(),
                                             filter_conditions=filter_conditions,
                                             order_by_list=order_by_list,
                                             offset=offset, limit=limit)
        # 关联查询所属环境信息
        filter_ids = [ft.id for ft in filters]
        project_dict = db.session.query(Filter.id, Project.name). \
            join(Project, Filter.project_id == Project.id). \
            filter(Filter.id.in_(filter_ids)). \
            all()
        project_dict = list2dict(project_dict)

        results = list()
        for ft in filters:
            results.append({
                'id': ft.id,
                'project': project_dict.get(ft.id),
                'filename': ft.filename,
                'status': 1 if ft.content else 0,
                'create_by': ft.create_by,
                'create_time': timestamp_obj_to_str(ft.create_time)
            })

        resp = {
            "data": {
                "rows": results,
                "total": count
            }
        }
        return jsonify(resp)


class FilterListView(FilterPermissionMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'codes-filter-list'

    def get(self):
        return render_template('codes/filter_list.html')


class FilterUpdateView(FilterPermissionMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'codes-filter-update'

    def get(self, pk):
        instance = db.session.query(Filter).get(pk)
        content = {
            'id': instance.id,
            'project_id': instance.project_id,
            'filename': instance.filename,
            'content': instance.content,
        }
        return render_template('codes/filter_update.html', **content)

    def post(self, pk):
        form = FilterForm(request.values)
        instance = db.session.query(Filter).get(pk)
        if form.validate():
            _clean_data = form.data
            if instance.filename != _clean_data.get('filename') or instance.project_id != _clean_data.get('project_id'):
                if db.session.query(Filter).filter_by(
                    project_id=_clean_data.get('project_id'),
                    filename=_clean_data.get('filename')
                ).count():
                    return response.params_error({
                        'field': 'filename',
                        'message': '该项目已有此文件'
                    })

            instance.project_id = _clean_data.get('project_id')
            instance.filename = _clean_data.get('filename').rstrip('/').lstrip('/')
            instance.content = _clean_data.get('content')
            instance.update()
            return response.success()
        else:
            return response.params_error(form.get_error())


class FilterCreateView(FilterPermissionMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'codes-filter-create'

    def get(self):
        return render_template('codes/filter_create.html')

    def post(self):
        form = FilterForm(request.values)
        if form.validate():
            _clean_data = form.data
            if db.session.query(Filter).filter_by(
                project_id=_clean_data.get('project_id'),
                filename=_clean_data.get('filename')
            ).count():
                return response.params_error({
                    'field': 'filename',
                    'message': '该项目已有此文件'
                })

            ft = Filter()
            ft.project_id = _clean_data.get('project_id')
            ft.filename = _clean_data.get('filename').rstrip('/').lstrip('/')
            ft.content = _clean_data.get('content')
            ft.create_by = current_user.name
            db.session.add(ft)
            db.session.commit()
            return response.success()
        else:
            return response.params_error(form.get_error())


class FilterDeleteView(FilterPermissionMixin, LoginRequiredMixin, views.MethodView):
    permission_required = 'codes-filter-delete'

    def post(self, pk):
        instance = db.session.query(Filter).get(pk)
        instance.delete()
        return response.success()

